From: Lionel Sambuc Date: Tue, 22 Jan 2013 11:03:53 +0000 (+0100) Subject: Termcap update, replacing elvis by nvi. X-Git-Tag: v3.2.1~76 X-Git-Url: http://zhaoyanbai.com/repos/rndc.html?a=commitdiff_plain;h=3e1db26a5a6252fcff0898d4cb0c3fa16ccf561d;p=minix.git Termcap update, replacing elvis by nvi. Removing elvis, importing nvi, ctags, updating libedit. Change-Id: I881eb04d2dc64cf112facd992de1114e1a59107f --- diff --git a/commands/Makefile b/commands/Makefile index ffd193b64..4c2c94c09 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -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 index 2dcfedf7a..000000000 --- a/commands/elvis/.descr +++ /dev/null @@ -1 +0,0 @@ -Lightweight vi diff --git a/commands/elvis/Doc.sh b/commands/elvis/Doc.sh deleted file mode 100755 index 88479f19d..000000000 --- a/commands/elvis/Doc.sh +++ /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 versions function keys. -X-DNO_CTRL_FKEY removes support for the and versions function keys. -X-DNO_SHIFT_FKEY removes support for the , , and 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 "#" -Xto map function key . -XFor example, ":map #1 {!}fmt^M" will cause the 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 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 +, -X"#1c" to refer to +, and -X"#1a" to refer to +. -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 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 ... -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 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 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 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 from ? -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 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 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 key on a DEC keyboard? -X.AA -XI don't know. Maybe the key? -XYou could always use ":map!" to make some other key act like the key. -XIf all else fails, use <[>. -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, /\\/ 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 key -X:kl=: sequence sent by the key -X:kr=: sequence sent by the key -X:ku=: sequence sent by the key -X:kP=: sequence sent by the key -X:kN=: sequence sent by the key -X:kh=: sequence sent by the key -X:kH=: sequence sent by the key -X:kI=: sequence sent by the key -X.DE -X.PP -XOriginally, termcap didn't have any names for the , , , -Xand 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 through keys -X:s1=:...:s9=:s0=: codes sent by ... -X:c1=:...:c9=:c0=: codes sent by ... -X:a1=:...:a9=:a0=: codes sent by ... -X.DE -X.PP -XNote that :k0=: is used to describe the key. -XSome termcap documents recommend :ka=: or even :k;=: for describing -Xthe 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 -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 index 740074ddd..000000000 --- a/commands/elvis/Knownbug.txt +++ /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 index 23202638e..000000000 --- a/commands/elvis/Makedoc +++ /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 index b0f8d85eb..000000000 --- a/commands/elvis/Makefile +++ /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 index 5dc7f875b..000000000 --- a/commands/elvis/Man.sh +++ /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 index dc7656f99..000000000 --- a/commands/elvis/Readme.txt +++ /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 index db41d9320..000000000 --- a/commands/elvis/blk.c +++ /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 index 493005267..000000000 --- a/commands/elvis/cmd1.c +++ /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 index 5d88acc1f..000000000 --- a/commands/elvis/cmd2.c +++ /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 index 38af7e843..000000000 --- a/commands/elvis/config.h +++ /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 index 700138a58..000000000 --- a/commands/elvis/ctags.c +++ /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 index ac6118307..000000000 --- a/commands/elvis/ctype.c +++ /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 index 1a46fd379..000000000 --- a/commands/elvis/ctype.h +++ /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 index f8cc76742..000000000 --- a/commands/elvis/curses.c +++ /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 index 84c897cf7..000000000 --- a/commands/elvis/curses.h +++ /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 index 0e0bb393f..000000000 --- a/commands/elvis/cut.c +++ /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 index f5ee575f3..000000000 --- a/commands/elvis/elvprsv.c +++ /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 index 4e9c389ea..000000000 --- a/commands/elvis/elvrec.c +++ /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 index 064e66208..000000000 --- a/commands/elvis/ex.c +++ /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 index 72fe85848..000000000 --- a/commands/elvis/fmt.c +++ /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 index 563f64351..000000000 --- a/commands/elvis/input.c +++ /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 index 0198b8be4..000000000 --- a/commands/elvis/main.c +++ /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 index c9e0f689d..000000000 --- a/commands/elvis/misc.c +++ /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 index af7914601..000000000 --- a/commands/elvis/modify.c +++ /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 index f57ab9a0a..000000000 --- a/commands/elvis/move1.c +++ /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 index b664153cb..000000000 --- a/commands/elvis/move2.c +++ /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 index a9e46ea8a..000000000 --- a/commands/elvis/move3.c +++ /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 index a31ef881f..000000000 --- a/commands/elvis/move4.c +++ /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 index aec5e785b..000000000 --- a/commands/elvis/move5.c +++ /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 index 7552ac6fb..000000000 --- a/commands/elvis/opts.c +++ /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 index 4af722e66..000000000 --- a/commands/elvis/prsvunix.c +++ /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 index 421603610..000000000 --- a/commands/elvis/recycle.c +++ /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 index ae923cf60..000000000 --- a/commands/elvis/redraw.c +++ /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 index c830464ae..000000000 --- a/commands/elvis/ref.c +++ /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 index 91db71af8..000000000 --- a/commands/elvis/regexp.c +++ /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 index 6d043b027..000000000 --- a/commands/elvis/regexp.h +++ /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 index d9ea1a153..000000000 --- a/commands/elvis/regsub.c +++ /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 index e73bc5a92..000000000 --- a/commands/elvis/system.c +++ /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 index c67add651..000000000 --- a/commands/elvis/tinyprnt.c +++ /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 index 922260fe9..000000000 --- a/commands/elvis/tinytcap.c +++ /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 index 66bd26183..000000000 --- a/commands/elvis/tio.c +++ /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 index 9102169d8..000000000 --- a/commands/elvis/tmp.c +++ /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 index f366d2673..000000000 --- a/commands/elvis/unix.c +++ /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 index 19b5d193a..000000000 --- a/commands/elvis/vars.c +++ /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 index 494f7e1f7..000000000 --- a/commands/elvis/vcmd.c +++ /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 index 24c46dc3f..000000000 --- a/commands/elvis/vi.c +++ /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 index 4c42dd2fc..000000000 --- a/commands/elvis/vi.h +++ /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 index 000000000..b8329baea --- /dev/null +++ b/dist/nvi/Changes @@ -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 index 000000000..64de8c764 --- /dev/null +++ b/dist/nvi/LICENSE @@ -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 index 000000000..5d831860d --- /dev/null +++ b/dist/nvi/README @@ -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 index 000000000..671c1bc7a --- /dev/null +++ b/dist/nvi/README.1st @@ -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 index 000000000..58b4a6237 --- /dev/null +++ b/dist/nvi/README.DB3 @@ -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 index 000000000..f0667c425 --- /dev/null +++ b/dist/nvi/TODO @@ -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 index 000000000..eb528147a --- /dev/null +++ b/dist/nvi/build.unix/README @@ -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 index 000000000..2cc68dafc --- /dev/null +++ b/dist/nvi/build.unix/README.LynxOS @@ -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 index 000000000..c2a73447d --- /dev/null +++ b/dist/nvi/build.unix/README.Solaris @@ -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 index 000000000..2a3652d68 --- /dev/null +++ b/dist/nvi/catalog/Makefile @@ -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 index 000000000..a110db16d --- /dev/null +++ b/dist/nvi/catalog/README @@ -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 index 000000000..114ff5a54 --- /dev/null +++ b/dist/nvi/catalog/dump.c @@ -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 index 000000000..4886c91f4 --- /dev/null +++ b/dist/nvi/catalog/dutch.base @@ -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 index 000000000..27f47d30d --- /dev/null +++ b/dist/nvi/catalog/dutch.owner @@ -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 index 000000000..034567ddd --- /dev/null +++ b/dist/nvi/catalog/english.owner @@ -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 index 000000000..7733947af --- /dev/null +++ b/dist/nvi/catalog/french.base @@ -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‚finition : l'option de %s doit ˆtre en groupe de deux caractŠres" +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 index 000000000..64b30bb0d --- /dev/null +++ b/dist/nvi/catalog/german.base @@ -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 index 000000000..efed56a0a --- /dev/null +++ b/dist/nvi/catalog/german.owner @@ -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 index 000000000..a52532df5 --- /dev/null +++ b/dist/nvi/catalog/ru_RU.KOI8-R.base @@ -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 index 000000000..35aa5c96f --- /dev/null +++ b/dist/nvi/catalog/ru_RU.KOI8-R.owner @@ -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 index 000000000..64514bc8b --- /dev/null +++ b/dist/nvi/catalog/spanish.base @@ -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‚s 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‚rprete 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‚rprete 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 index 000000000..00be47141 --- /dev/null +++ b/dist/nvi/catalog/spell.ok @@ -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 index 000000000..8582e450e --- /dev/null +++ b/dist/nvi/catalog/swedish.base @@ -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 index 000000000..2b36f2d32 --- /dev/null +++ b/dist/nvi/catalog/swedish.owner @@ -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 index 000000000..cf17a6b3d --- /dev/null +++ b/dist/nvi/cl/README.signal @@ -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 index 000000000..d0e9ea57c --- /dev/null +++ b/dist/nvi/cl/cl.h @@ -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 index 000000000..e4f20b71a --- /dev/null +++ b/dist/nvi/cl/cl_bsd.c @@ -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 index 000000000..10ed2bc50 --- /dev/null +++ b/dist/nvi/cl/cl_funcs.c @@ -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 index 000000000..84cad2fee --- /dev/null +++ b/dist/nvi/cl/cl_main.c @@ -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 index 000000000..8e5b87686 --- /dev/null +++ b/dist/nvi/cl/cl_read.c @@ -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 index 000000000..ef4ac3d08 --- /dev/null +++ b/dist/nvi/cl/cl_screen.c @@ -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 index 000000000..5655f7758 --- /dev/null +++ b/dist/nvi/cl/cl_term.c @@ -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 index 000000000..8f91515f5 --- /dev/null +++ b/dist/nvi/cl/extern.h @@ -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 index 000000000..e31161415 --- /dev/null +++ b/dist/nvi/clib/bsearch.c @@ -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 index 000000000..ccd3593cc --- /dev/null +++ b/dist/nvi/clib/env.c @@ -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 index 000000000..d53dbf94c --- /dev/null +++ b/dist/nvi/clib/gethostname.c @@ -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 index 000000000..930363e83 --- /dev/null +++ b/dist/nvi/clib/iswblank.c @@ -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 index 000000000..ddeff5f66 --- /dev/null +++ b/dist/nvi/clib/memchr.c @@ -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 index 000000000..ae463db53 --- /dev/null +++ b/dist/nvi/clib/memset.c @@ -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 index 000000000..d7a8060e9 --- /dev/null +++ b/dist/nvi/clib/mkstemp.c @@ -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 index 000000000..4cf6e5516 --- /dev/null +++ b/dist/nvi/clib/mmap.c @@ -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 index 000000000..b814660df --- /dev/null +++ b/dist/nvi/clib/snprintf.c @@ -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 index 000000000..342a64d77 --- /dev/null +++ b/dist/nvi/clib/strdup.c @@ -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 index 000000000..e6cc9533c --- /dev/null +++ b/dist/nvi/clib/strpbrk.c @@ -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 index 000000000..cf92a4c94 --- /dev/null +++ b/dist/nvi/clib/strsep.c @@ -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 index 000000000..042e01f7e --- /dev/null +++ b/dist/nvi/clib/strtol.c @@ -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 index 000000000..c61030d57 --- /dev/null +++ b/dist/nvi/clib/strtoul.c @@ -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 index 000000000..e9533e30a --- /dev/null +++ b/dist/nvi/clib/vsnprintf.c @@ -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 index 000000000..9d2a2720e --- /dev/null +++ b/dist/nvi/common/api.c @@ -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 index 000000000..92c461c26 --- /dev/null +++ b/dist/nvi/common/args.h @@ -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 index 000000000..8d1dc2432 --- /dev/null +++ b/dist/nvi/common/common.h @@ -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 index 000000000..042af1248 --- /dev/null +++ b/dist/nvi/common/conv.c @@ -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 index 000000000..f655ac3ad --- /dev/null +++ b/dist/nvi/common/conv.h @@ -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 index 000000000..971087fe2 --- /dev/null +++ b/dist/nvi/common/cut.c @@ -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 index 000000000..e4bcf6d6d --- /dev/null +++ b/dist/nvi/common/cut.h @@ -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 index 000000000..f5f9c0035 --- /dev/null +++ b/dist/nvi/common/db.c @@ -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 index 000000000..d3bef8ec0 --- /dev/null +++ b/dist/nvi/common/db.h @@ -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 index 000000000..082e8bee1 --- /dev/null +++ b/dist/nvi/common/db1.c @@ -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 index 000000000..35856fc22 --- /dev/null +++ b/dist/nvi/common/dbinternal.h @@ -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 index 000000000..36e52e973 --- /dev/null +++ b/dist/nvi/common/delete.c @@ -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 index 000000000..685079ded --- /dev/null +++ b/dist/nvi/common/dldb.c @@ -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 index 000000000..de9a18623 --- /dev/null +++ b/dist/nvi/common/exf.c @@ -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 index 000000000..7d5b41dd2 --- /dev/null +++ b/dist/nvi/common/exf.h @@ -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 index 000000000..b65e0b4f9 --- /dev/null +++ b/dist/nvi/common/extern.h @@ -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 index 000000000..3e3bb46cb --- /dev/null +++ b/dist/nvi/common/gs.c @@ -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 index 000000000..3198eaf81 --- /dev/null +++ b/dist/nvi/common/gs.h @@ -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 index 000000000..249ea1126 --- /dev/null +++ b/dist/nvi/common/key.c @@ -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 index 000000000..8c30d6122 --- /dev/null +++ b/dist/nvi/common/key.h @@ -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 index 000000000..d61e8d2c4 --- /dev/null +++ b/dist/nvi/common/log.c @@ -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 index 000000000..06e0e1231 --- /dev/null +++ b/dist/nvi/common/log.h @@ -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 index 000000000..615a18a56 --- /dev/null +++ b/dist/nvi/common/log4.c @@ -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 index 000000000..60218a20d --- /dev/null +++ b/dist/nvi/common/main.c @@ -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 index 000000000..30653bc86 --- /dev/null +++ b/dist/nvi/common/mark.c @@ -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 index 000000000..32a30ec08 --- /dev/null +++ b/dist/nvi/common/mark.h @@ -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 index 000000000..c87b2c721 --- /dev/null +++ b/dist/nvi/common/mem.h @@ -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 index 000000000..31a822239 --- /dev/null +++ b/dist/nvi/common/msg.c @@ -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 index 000000000..ad1c677fd --- /dev/null +++ b/dist/nvi/common/msg.h @@ -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 index 000000000..7a94d7611 --- /dev/null +++ b/dist/nvi/common/multibyte.h @@ -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 index 000000000..446c3b004 --- /dev/null +++ b/dist/nvi/common/nothread.c @@ -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 index 000000000..0b81bb526 --- /dev/null +++ b/dist/nvi/common/options.awk @@ -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 index 000000000..90d252b7d --- /dev/null +++ b/dist/nvi/common/options.c @@ -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 index 000000000..1a5825f11 --- /dev/null +++ b/dist/nvi/common/options.h @@ -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 index 000000000..3807553c9 --- /dev/null +++ b/dist/nvi/common/options_f.c @@ -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 index 000000000..8ea57897c --- /dev/null +++ b/dist/nvi/common/pthread.c @@ -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 index 000000000..e244150ca --- /dev/null +++ b/dist/nvi/common/put.c @@ -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 index 000000000..5d426ffac --- /dev/null +++ b/dist/nvi/common/recover.c @@ -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 index 000000000..86981ed0c --- /dev/null +++ b/dist/nvi/common/screen.c @@ -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 index 000000000..8da0ad593 --- /dev/null +++ b/dist/nvi/common/screen.h @@ -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 index 000000000..5317e6b36 --- /dev/null +++ b/dist/nvi/common/search.c @@ -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 index 000000000..4361ba235 --- /dev/null +++ b/dist/nvi/common/seq.c @@ -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 index 000000000..41c50134f --- /dev/null +++ b/dist/nvi/common/seq.h @@ -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 index 000000000..ae0c5b961 --- /dev/null +++ b/dist/nvi/common/trace.c @@ -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 index 000000000..6fc793fd2 --- /dev/null +++ b/dist/nvi/common/util.c @@ -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 index 000000000..3777c0015 --- /dev/null +++ b/dist/nvi/common/util.h @@ -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 index 000000000..56391dec7 --- /dev/null +++ b/dist/nvi/common/util2.c @@ -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 index 000000000..713c16464 --- /dev/null +++ b/dist/nvi/common/vi.src @@ -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 index 000000000..b0f33f194 --- /dev/null +++ b/dist/nvi/common/vi_auto.c @@ -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 index 000000000..e19509ed9 --- /dev/null +++ b/dist/nvi/common/vi_auto.h @@ -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 index 000000000..f11bd5234 --- /dev/null +++ b/dist/nvi/common/vi_rec.c @@ -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 index 000000000..4cb97856f --- /dev/null +++ b/dist/nvi/dist/ExtUtils/Embed.pm @@ -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 index 000000000..b42a17ac4 --- /dev/null +++ b/dist/nvi/dist/INSTALL @@ -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 index 000000000..c1d6871a8 --- /dev/null +++ b/dist/nvi/dist/Makefile.am @@ -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 index 000000000..7bca817f9 --- /dev/null +++ b/dist/nvi/dist/Makefile.in @@ -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 index 000000000..83ba4f191 --- /dev/null +++ b/dist/nvi/dist/acconfig.h @@ -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 index 000000000..6b8a4a123 --- /dev/null +++ b/dist/nvi/dist/aclocal.m4 @@ -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 index 000000000..9bb997a6a --- /dev/null +++ b/dist/nvi/dist/compile @@ -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 index 000000000..951383e35 --- /dev/null +++ b/dist/nvi/dist/config.guess @@ -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 index 000000000..c1bda3e98 --- /dev/null +++ b/dist/nvi/dist/config.h.in @@ -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 index 000000000..c060f4483 --- /dev/null +++ b/dist/nvi/dist/config.sub @@ -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 index 000000000..b23e1677e --- /dev/null +++ b/dist/nvi/dist/configure @@ -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, µ) != 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 index 000000000..082aa60c9 --- /dev/null +++ b/dist/nvi/dist/configure.in @@ -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 index 000000000..65899658e --- /dev/null +++ b/dist/nvi/dist/depcomp @@ -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 index 000000000..4faa66b90 --- /dev/null +++ b/dist/nvi/dist/distrib @@ -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 index 000000000..c0fe056ef --- /dev/null +++ b/dist/nvi/dist/export @@ -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 index 000000000..166a03dab --- /dev/null +++ b/dist/nvi/dist/findconfig @@ -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 index 000000000..4fbbae7b7 --- /dev/null +++ b/dist/nvi/dist/install-sh @@ -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 index 000000000..a362c48d3 --- /dev/null +++ b/dist/nvi/dist/ltconfig @@ -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 index 000000000..4598ec61c --- /dev/null +++ b/dist/nvi/dist/ltmain.sh @@ -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 index 000000000..b8cf4024a --- /dev/null +++ b/dist/nvi/dist/m4/gtk.m4 @@ -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, µ) != 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 index 000000000..0a7fb5a2a --- /dev/null +++ b/dist/nvi/dist/missing @@ -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 index 000000000..f35df973f --- /dev/null +++ b/dist/nvi/dist/mkinstalldirs @@ -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 index 000000000..6ca0a05df --- /dev/null +++ b/dist/nvi/dist/pathnames.h.in @@ -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 index 000000000..b1d05d143 --- /dev/null +++ b/dist/nvi/dist/port.h.in @@ -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 index 000000000..8a5eaa748 --- /dev/null +++ b/dist/nvi/dist/recover.in @@ -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 index 000000000..7bb2b4f3f --- /dev/null +++ b/dist/nvi/dist/script @@ -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 index 000000000..fc103f436 --- /dev/null +++ b/dist/nvi/dist/spell.ok @@ -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 index 000000000..e69de29bb diff --git a/dist/nvi/docs/README b/dist/nvi/docs/README new file mode 100644 index 000000000..3399dbee5 --- /dev/null +++ b/dist/nvi/docs/README @@ -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 index 000000000..803c7deaa --- /dev/null +++ b/dist/nvi/docs/edit/Makefile @@ -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 index 000000000..cada8b85a --- /dev/null +++ b/dist/nvi/docs/edit/edittut.ms @@ -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 index 000000000..61bc7a8da --- /dev/null +++ b/dist/nvi/docs/exref/Makefile @@ -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 index 000000000..37703f30b --- /dev/null +++ b/dist/nvi/docs/exref/ex.rm @@ -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 index 000000000..1f3d4b97c --- /dev/null +++ b/dist/nvi/docs/exref/ex.summary @@ -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 index 000000000..de4914ec8 --- /dev/null +++ b/dist/nvi/docs/vi.man/Makefile @@ -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 index 000000000..80ebcaba8 --- /dev/null +++ b/dist/nvi/docs/vi.man/spell.ok @@ -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 index 000000000..38efb8779 --- /dev/null +++ b/dist/nvi/docs/vi.man/vi.1 @@ -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 index 000000000..7896b1c10 --- /dev/null +++ b/dist/nvi/docs/vi.ref/Makefile @@ -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 index 000000000..33af6e706 --- /dev/null +++ b/dist/nvi/docs/vi.ref/ex.cmd.texi @@ -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 index 000000000..97f83304d --- /dev/null +++ b/dist/nvi/docs/vi.ref/ref.texi @@ -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 index 000000000..b2332a97e --- /dev/null +++ b/dist/nvi/docs/vi.ref/set.opt.texi @@ -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 index 000000000..a7d95e35d --- /dev/null +++ b/dist/nvi/docs/vi.ref/spell.ok @@ -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 index 000000000..80400cfae --- /dev/null +++ b/dist/nvi/docs/vi.ref/vi.cmd.texi @@ -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 index 000000000..964f2ba90 --- /dev/null +++ b/dist/nvi/docs/vi.ref/vi.texi @@ -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 index 000000000..5a1f1959a --- /dev/null +++ b/dist/nvi/docs/vitut/Makefile @@ -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 index 000000000..ac722ea97 --- /dev/null +++ b/dist/nvi/docs/vitut/vi.apwh.ms @@ -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 index 000000000..f246b6613 --- /dev/null +++ b/dist/nvi/docs/vitut/vi.chars @@ -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 " +.iP  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  +.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 index 000000000..845099a3b --- /dev/null +++ b/dist/nvi/docs/vitut/vi.in @@ -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 index 000000000..a7af400e9 --- /dev/null +++ b/dist/nvi/docs/vitut/vi.summary @@ -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 \\$1H .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 index 000000000..9cbb53f20 --- /dev/null +++ b/dist/nvi/ex/ex.awk @@ -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 index 000000000..d26bedeb5 --- /dev/null +++ b/dist/nvi/ex/ex.c @@ -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, <mp, 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 index 000000000..842c99b4a --- /dev/null +++ b/dist/nvi/ex/ex.h @@ -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 index 000000000..0fe90ef12 --- /dev/null +++ b/dist/nvi/ex/ex_abbrev.c @@ -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 index 000000000..68b4daf27 --- /dev/null +++ b/dist/nvi/ex/ex_append.c @@ -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 index 000000000..ae6790651 --- /dev/null +++ b/dist/nvi/ex/ex_args.c @@ -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 index 000000000..344a142b7 --- /dev/null +++ b/dist/nvi/ex/ex_argv.c @@ -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 index 000000000..23d7b0322 --- /dev/null +++ b/dist/nvi/ex/ex_at.c @@ -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 index 000000000..e88c53306 --- /dev/null +++ b/dist/nvi/ex/ex_bang.c @@ -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 index 000000000..836f1548f --- /dev/null +++ b/dist/nvi/ex/ex_cd.c @@ -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 index 000000000..d3394216b --- /dev/null +++ b/dist/nvi/ex/ex_cmd.c @@ -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 index 000000000..cf3964956 --- /dev/null +++ b/dist/nvi/ex/ex_cscope.c @@ -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 index 000000000..8854f4b7d --- /dev/null +++ b/dist/nvi/ex/ex_def.h @@ -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 index 000000000..9d8e14911 --- /dev/null +++ b/dist/nvi/ex/ex_delete.c @@ -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 index 000000000..1ef1c6e40 --- /dev/null +++ b/dist/nvi/ex/ex_display.c @@ -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 index 000000000..af088f2b3 --- /dev/null +++ b/dist/nvi/ex/ex_edit.c @@ -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 index 000000000..ea10007de --- /dev/null +++ b/dist/nvi/ex/ex_equal.c @@ -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 index 000000000..be02abcc8 --- /dev/null +++ b/dist/nvi/ex/ex_file.c @@ -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 index 000000000..a23419fad --- /dev/null +++ b/dist/nvi/ex/ex_filter.c @@ -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 index 000000000..ff6ae5220 --- /dev/null +++ b/dist/nvi/ex/ex_global.c @@ -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 index 000000000..e8a044d5f --- /dev/null +++ b/dist/nvi/ex/ex_init.c @@ -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 index 000000000..bdaedbe1d --- /dev/null +++ b/dist/nvi/ex/ex_join.c @@ -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 index 000000000..4e53932a6 --- /dev/null +++ b/dist/nvi/ex/ex_map.c @@ -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 index 000000000..3e52c10e6 --- /dev/null +++ b/dist/nvi/ex/ex_mark.c @@ -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 index 000000000..5305d09c8 --- /dev/null +++ b/dist/nvi/ex/ex_mkexrc.c @@ -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 index 000000000..cecc537b3 --- /dev/null +++ b/dist/nvi/ex/ex_move.c @@ -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 index 000000000..45e018b7d --- /dev/null +++ b/dist/nvi/ex/ex_open.c @@ -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 index 000000000..a53dd2308 --- /dev/null +++ b/dist/nvi/ex/ex_perl.c @@ -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 index 000000000..51577f4d8 --- /dev/null +++ b/dist/nvi/ex/ex_preserve.c @@ -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 index 000000000..6ce2d9e36 --- /dev/null +++ b/dist/nvi/ex/ex_print.c @@ -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 index 000000000..2e5e6f07d --- /dev/null +++ b/dist/nvi/ex/ex_put.c @@ -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 index 000000000..38a87d8a0 --- /dev/null +++ b/dist/nvi/ex/ex_quit.c @@ -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 index 000000000..d0602ed62 --- /dev/null +++ b/dist/nvi/ex/ex_read.c @@ -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 index 000000000..8b0930f31 --- /dev/null +++ b/dist/nvi/ex/ex_screen.c @@ -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 index 000000000..fe1528190 --- /dev/null +++ b/dist/nvi/ex/ex_script.c @@ -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 index 000000000..7dfa4b30f --- /dev/null +++ b/dist/nvi/ex/ex_set.c @@ -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 index 000000000..0d4065c74 --- /dev/null +++ b/dist/nvi/ex/ex_shell.c @@ -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 index 000000000..4b19adbf8 --- /dev/null +++ b/dist/nvi/ex/ex_shift.c @@ -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 index 000000000..f1005a455 --- /dev/null +++ b/dist/nvi/ex/ex_source.c @@ -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 index 000000000..cde21fe10 --- /dev/null +++ b/dist/nvi/ex/ex_stop.c @@ -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 index 000000000..67c5c1fa3 --- /dev/null +++ b/dist/nvi/ex/ex_subst.c @@ -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 index 000000000..2a38b7e2b --- /dev/null +++ b/dist/nvi/ex/ex_tag.c @@ -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 index 000000000..4e24c5af2 --- /dev/null +++ b/dist/nvi/ex/ex_tcl.c @@ -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 index 000000000..ee10ac3f6 --- /dev/null +++ b/dist/nvi/ex/ex_txt.c @@ -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 index 000000000..c000b92d3 --- /dev/null +++ b/dist/nvi/ex/ex_undo.c @@ -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 index 000000000..020c20202 --- /dev/null +++ b/dist/nvi/ex/ex_usage.c @@ -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 index 000000000..b91e5e3d8 --- /dev/null +++ b/dist/nvi/ex/ex_util.c @@ -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 index 000000000..91696142d --- /dev/null +++ b/dist/nvi/ex/ex_version.c @@ -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 index 000000000..a403d45d0 --- /dev/null +++ b/dist/nvi/ex/ex_visual.c @@ -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 index 000000000..53f7eacc5 --- /dev/null +++ b/dist/nvi/ex/ex_write.c @@ -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 index 000000000..d172b4963 --- /dev/null +++ b/dist/nvi/ex/ex_yank.c @@ -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 index 000000000..b4331868e --- /dev/null +++ b/dist/nvi/ex/ex_z.c @@ -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 index 000000000..4703ec788 --- /dev/null +++ b/dist/nvi/ex/extern.h @@ -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 index 000000000..66a12f8f1 --- /dev/null +++ b/dist/nvi/ex/script.h @@ -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 index 000000000..fa6118584 --- /dev/null +++ b/dist/nvi/ex/tag.h @@ -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 index 000000000..5d3939ee9 --- /dev/null +++ b/dist/nvi/ex/version.h @@ -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 index 000000000..2a0743854 --- /dev/null +++ b/dist/nvi/gtk/extern.h @@ -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 index 000000000..12cf32d34 --- /dev/null +++ b/dist/nvi/gtk/gtk.h @@ -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 index 000000000..1407c554d --- /dev/null +++ b/dist/nvi/gtk/gtk_main.c @@ -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 index 000000000..83b28c639 --- /dev/null +++ b/dist/nvi/gtk/gtkvi.c @@ -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 index 000000000..ed3519db4 --- /dev/null +++ b/dist/nvi/gtk/gtkvi.h @@ -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 index 000000000..46d815081 --- /dev/null +++ b/dist/nvi/gtk/gtkviscreen.c @@ -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 index 000000000..d1744786d --- /dev/null +++ b/dist/nvi/gtk/gtkviscreen.h @@ -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 index 000000000..391b82c7d --- /dev/null +++ b/dist/nvi/gtk/gtkviwindow.c @@ -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 index 000000000..d94541ad5 --- /dev/null +++ b/dist/nvi/gtk/gtkviwindow.h @@ -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 index 000000000..af0f92cde --- /dev/null +++ b/dist/nvi/include/bitstring.h @@ -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 index 000000000..4d7010908 --- /dev/null +++ b/dist/nvi/include/sys/queue.h @@ -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 index 000000000..932bb2995 --- /dev/null +++ b/dist/nvi/ip/extern.h @@ -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 index 000000000..be381f116 --- /dev/null +++ b/dist/nvi/ip/ip_funcs.c @@ -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 index 000000000..5bb749e84 --- /dev/null +++ b/dist/nvi/ip/ip_main.c @@ -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 index 000000000..1bbc5b599 --- /dev/null +++ b/dist/nvi/ip/ip_read.c @@ -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 index 000000000..39293f7ae --- /dev/null +++ b/dist/nvi/ip/ip_screen.c @@ -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 index 000000000..5b3dcb719 --- /dev/null +++ b/dist/nvi/ip/ip_term.c @@ -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 index 000000000..c0d2a8db4 --- /dev/null +++ b/dist/nvi/ip/vipc.pl @@ -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 index 000000000..8555dae00 --- /dev/null +++ b/dist/nvi/ipc/extern.h @@ -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 index 000000000..7223f100e --- /dev/null +++ b/dist/nvi/ipc/ip.h @@ -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 index 000000000..94c27ffb5 --- /dev/null +++ b/dist/nvi/ipc/ip_run.c @@ -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 index 000000000..4348ff674 --- /dev/null +++ b/dist/nvi/ipc/ip_send.c @@ -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 index 000000000..2f88bf9ce --- /dev/null +++ b/dist/nvi/ipc/ip_trans.c @@ -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 index 000000000..828a642c8 --- /dev/null +++ b/dist/nvi/ipc/ipc.awk @@ -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 index 000000000..651969590 --- /dev/null +++ b/dist/nvi/ipc/ipc_cmd.c @@ -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 index 000000000..ac910dc27 --- /dev/null +++ b/dist/nvi/ipc/ipc_def.h @@ -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 index 000000000..6fdc31f57 --- /dev/null +++ b/dist/nvi/ipc/ipc_gen.c @@ -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 index 000000000..ad7db843d --- /dev/null +++ b/dist/nvi/ipc/ipc_method.c @@ -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 index 000000000..8e1305d7b --- /dev/null +++ b/dist/nvi/ipc/vipc.awk @@ -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 index 000000000..625466818 --- /dev/null +++ b/dist/nvi/motif/extern.h @@ -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 index 000000000..f06a1b373 --- /dev/null +++ b/dist/nvi/motif/m_cde.c @@ -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 index 000000000..13cf28502 --- /dev/null +++ b/dist/nvi/motif/m_main.c @@ -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 + + +/* 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; +} + + +/* 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" ) ); +} + + +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 index 000000000..a9d4e2346 --- /dev/null +++ b/dist/nvi/motif/nvi.xbm @@ -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 index 000000000..b891caca7 --- /dev/null +++ b/dist/nvi/motif/nvi.xpm @@ -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 index 000000000..0dcd60a58 --- /dev/null +++ b/dist/nvi/motif_l/TODO @@ -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 index 000000000..fd7b15701 --- /dev/null +++ b/dist/nvi/motif_l/extern.h @@ -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 index 000000000..b74091421 --- /dev/null +++ b/dist/nvi/motif_l/m_copypaste.c @@ -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 index 000000000..64cc0aa83 --- /dev/null +++ b/dist/nvi/motif_l/m_func.c @@ -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" + + +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 index 000000000..d5d458017 --- /dev/null +++ b/dist/nvi/motif_l/m_menu.c @@ -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); +} + + +/* 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 ); +} + + +/* + * __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) ); +} + + +/* 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; +} + + +/* + * 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); + } +} + + +/* + * 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" ); +} + + +/* 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 index 000000000..d919552a8 --- /dev/null +++ b/dist/nvi/motif_l/m_motif.h @@ -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 index 000000000..7ab684505 --- /dev/null +++ b/dist/nvi/motif_l/m_options.c @@ -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)); + + +/* constants */ + +#if defined(SelfTest) + +/* in production, get these from the resource list */ + +#define toggleColumns 6 + +#endif + + +/* + * 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, + }, +}; + + +/* 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(); + } +} + + +/* 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; +} + + +/* 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 ); + } +} + + +/* 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; +} + + +/* 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 ); +} + + +/* 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; +} + + + +/* + * 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 +} + + + +/* 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)); +} + + +#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 index 000000000..ab0595988 --- /dev/null +++ b/dist/nvi/motif_l/m_prompt.c @@ -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" + + +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); +} + + +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 index 000000000..5179d0ccf --- /dev/null +++ b/dist/nvi/motif_l/m_ruler.c @@ -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" + + +/* 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 + + +/* 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(); +} + + +/* 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; +} + + + +/* 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; +} + + + +/* 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) ); +} + + +#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 index 000000000..fc5083d5d --- /dev/null +++ b/dist/nvi/motif_l/m_search.c @@ -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; + + +/* types */ + +typedef struct sds { + struct sds *next; + Widget shell; +} save_dialog; + +static save_dialog *dialogs = NULL; + +typedef struct { + String name; + void (*cb)(); +} ButtonData; + + +/* 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 */ +}; + + +/* 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 ); +} + + +/* 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 ); + } +} + + +/* 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; +} + + +/* 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; +} + + +/* 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 + + +/* 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 */ + + +/* 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; +} + + +/* 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 ); +} + + +#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 index 000000000..41442ae5f --- /dev/null +++ b/dist/nvi/motif_l/m_tags.c @@ -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 + */ + + +/* 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; + + +/* 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 }, +}; + + +/* 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 ); +} + + +/* 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; +} + + +/* 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 ); +} + + + +/* 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; +} + + + +/* 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; +} + + + +#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 index 000000000..1dad783ac --- /dev/null +++ b/dist/nvi/motif_l/m_util.c @@ -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" + + +/* 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 + + +/* 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 index 000000000..e48ea2cff --- /dev/null +++ b/dist/nvi/motif_l/m_vi.c @@ -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); + + +/* + * 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. */ + + +/* 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; +} + + +#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; + } +} + + +/* + * Memory utilities + */ + +#ifdef REALLOC +#undef REALLOC +#endif + +#define REALLOC( ptr, size ) \ + ((ptr == NULL) ? malloc(size) : realloc(ptr,size)) + + +/* 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 +} + + + +/* 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); +} + + +#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 ); +} + + + +/* 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 + ); + } +} + + +/* 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 ); +} + + +/* + * __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; + } + +} + + +#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; +} + + +/* 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; +} + + +/* 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 ); +} + + +/* 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 ); +} + + +/* + * 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 + ); +} + + + +/* 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 : ""; +} + + +/* + * 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 index 000000000..616f348e2 --- /dev/null +++ b/dist/nvi/motif_l/vi_mextern.h @@ -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 index 000000000..1d27d5992 --- /dev/null +++ b/dist/nvi/motif_l/xtabbed.c @@ -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 + * *********************************************************************** + */ + + +#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> + + +/* *********************************************************************** + * "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_ */ + + + + +/* *********************************************************************** + * "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_ */ + + +/* *********************************************************************** + * "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_*/ + + +/* *********************************************************************** + * "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_ */ + + +/* *********************************************************************** + * 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); +} + + +/* *********************************************************************** + * 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; +} + + + +/* *********************************************************************** + * 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); +} + + +/* *********************************************************************** + * 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 index 000000000..a5c6ff97f --- /dev/null +++ b/dist/nvi/nvi2netbsd @@ -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 index 000000000..f73a93656 --- /dev/null +++ b/dist/nvi/perl_api/VI.pod @@ -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 index 000000000..42223c0d8 --- /dev/null +++ b/dist/nvi/perl_api/extern.h @@ -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 index 000000000..432fbe985 --- /dev/null +++ b/dist/nvi/perl_api/nviperl.pod @@ -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 index 000000000..9c8bbd2b8 --- /dev/null +++ b/dist/nvi/perl_api/perl.xs @@ -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 index 000000000..3ba707d80 --- /dev/null +++ b/dist/nvi/perl_api/perlsfio.c @@ -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 index 000000000..1e0a43a7a --- /dev/null +++ b/dist/nvi/perl_api/typemap @@ -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 index 000000000..b9f85013b --- /dev/null +++ b/dist/nvi/perl_scripts/forall.pl @@ -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 index 000000000..54a9c86c8 --- /dev/null +++ b/dist/nvi/perl_scripts/make.pl @@ -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 index 000000000..f8d1bc068 --- /dev/null +++ b/dist/nvi/perl_scripts/tk.pl @@ -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 index 000000000..0a5015987 --- /dev/null +++ b/dist/nvi/perl_scripts/wc.pl @@ -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 index 000000000..574f6bcec --- /dev/null +++ b/dist/nvi/regex/COPYRIGHT @@ -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 index 000000000..f4301d300 --- /dev/null +++ b/dist/nvi/regex/WHATSNEW @@ -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 index 000000000..f28bccdfa --- /dev/null +++ b/dist/nvi/regex/cclass.h @@ -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 index 000000000..da69843df --- /dev/null +++ b/dist/nvi/regex/cname.h @@ -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 index 000000000..06dd4ec71 --- /dev/null +++ b/dist/nvi/regex/engine.c @@ -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®_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®_NOSUB) + nmatch = 0; + if (eflags®_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®_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®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOL: + if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OBOW: + if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_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®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_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®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flag = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_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®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flag = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_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®_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®_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 index 000000000..61d1aeaa8 --- /dev/null +++ b/dist/nvi/regex/re_format.7 @@ -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 index 000000000..7d198687e --- /dev/null +++ b/dist/nvi/regex/regcomp.c @@ -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®_EXTENDED) && (cflags®_NOSPEC)) + return(REG_INVARG); + + if (cflags®_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®_EXTENDED) + p_ere(p, OUT, 0); + else if (cflags®_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®_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®_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®_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®_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®_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 index 000000000..0b528d018 --- /dev/null +++ b/dist/nvi/regex/regerror.c @@ -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®_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 index 000000000..2c17254c1 --- /dev/null +++ b/dist/nvi/regex/regex.3 @@ -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 index 000000000..10c5c9334 --- /dev/null +++ b/dist/nvi/regex/regex.h @@ -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 index 000000000..7c9352831 --- /dev/null +++ b/dist/nvi/regex/regex2.h @@ -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 index 000000000..f3d3e068a --- /dev/null +++ b/dist/nvi/regex/regexec.c @@ -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®_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 index 000000000..61df17cb6 --- /dev/null +++ b/dist/nvi/regex/regfree.c @@ -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 index 000000000..4a6f57a3f --- /dev/null +++ b/dist/nvi/regex/utils.h @@ -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 index 000000000..c3ce610cd --- /dev/null +++ b/dist/nvi/tcl_api/extern.h @@ -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 index 000000000..a2ddaf7da --- /dev/null +++ b/dist/nvi/tcl_api/tcl.c @@ -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 index 000000000..9bc4407e7 --- /dev/null +++ b/dist/nvi/tcl_scripts/errors.tcl @@ -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  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  findErr +} diff --git a/dist/nvi/tcl_scripts/gnats.tcl b/dist/nvi/tcl_scripts/gnats.tcl new file mode 100644 index 000000000..bdd7d83ad --- /dev/null +++ b/dist/nvi/tcl_scripts/gnats.tcl @@ -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  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 index 000000000..5ead7a53b --- /dev/null +++ b/dist/nvi/tcl_scripts/mailprocs.tcl @@ -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  isAliasedLine +viMapKey $viScreenId  validLine diff --git a/dist/nvi/tcl_scripts/wc.tcl b/dist/nvi/tcl_scripts/wc.tcl new file mode 100644 index 000000000..357c65440 --- /dev/null +++ b/dist/nvi/tcl_scripts/wc.tcl @@ -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 index 000000000..312b475ce --- /dev/null +++ b/dist/nvi/vi/extern.h @@ -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 index 000000000..b02dd9abf --- /dev/null +++ b/dist/nvi/vi/getc.c @@ -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 index 000000000..5ff291cf9 --- /dev/null +++ b/dist/nvi/vi/v_at.c @@ -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 index 000000000..efb79af19 --- /dev/null +++ b/dist/nvi/vi/v_ch.c @@ -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 index 000000000..933dae213 --- /dev/null +++ b/dist/nvi/vi/v_cmd.c @@ -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 index 000000000..2af51ff77 --- /dev/null +++ b/dist/nvi/vi/v_delete.c @@ -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 index 000000000..38a7fac3b --- /dev/null +++ b/dist/nvi/vi/v_event.c @@ -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 index 000000000..2bc7c0f0b --- /dev/null +++ b/dist/nvi/vi/v_ex.c @@ -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 index 000000000..676b48cac --- /dev/null +++ b/dist/nvi/vi/v_increment.c @@ -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 index 000000000..476afe3fa --- /dev/null +++ b/dist/nvi/vi/v_init.c @@ -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 index 000000000..c94d64e85 --- /dev/null +++ b/dist/nvi/vi/v_itxt.c @@ -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 index 000000000..8827e9584 --- /dev/null +++ b/dist/nvi/vi/v_left.c @@ -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 index 000000000..b54d0eee1 --- /dev/null +++ b/dist/nvi/vi/v_mark.c @@ -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 index 000000000..be80b9a43 --- /dev/null +++ b/dist/nvi/vi/v_match.c @@ -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 index 000000000..88914394c --- /dev/null +++ b/dist/nvi/vi/v_paragraph.c @@ -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 index 000000000..3cb08d7fa --- /dev/null +++ b/dist/nvi/vi/v_put.c @@ -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 index 000000000..9789d13ff --- /dev/null +++ b/dist/nvi/vi/v_redraw.c @@ -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 index 000000000..faf2d1605 --- /dev/null +++ b/dist/nvi/vi/v_replace.c @@ -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 index 000000000..9f38dfc65 --- /dev/null +++ b/dist/nvi/vi/v_right.c @@ -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 index 000000000..efe4b8428 --- /dev/null +++ b/dist/nvi/vi/v_screen.c @@ -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 index 000000000..e163a9a2a --- /dev/null +++ b/dist/nvi/vi/v_scroll.c @@ -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 index 000000000..4ded14a58 --- /dev/null +++ b/dist/nvi/vi/v_search.c @@ -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 index 000000000..03cc3821e --- /dev/null +++ b/dist/nvi/vi/v_section.c @@ -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 index 000000000..9ee151d57 --- /dev/null +++ b/dist/nvi/vi/v_sentence.c @@ -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 index 000000000..7a7850fe9 --- /dev/null +++ b/dist/nvi/vi/v_status.c @@ -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 index 000000000..3a25e8c9f --- /dev/null +++ b/dist/nvi/vi/v_txt.c @@ -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 index 000000000..870eef831 --- /dev/null +++ b/dist/nvi/vi/v_ulcase.c @@ -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 index 000000000..ff958c08d --- /dev/null +++ b/dist/nvi/vi/v_undo.c @@ -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 index 000000000..0335bc940 --- /dev/null +++ b/dist/nvi/vi/v_util.c @@ -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 index 000000000..33d48819d --- /dev/null +++ b/dist/nvi/vi/v_word.c @@ -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 index 000000000..a47ad6882 --- /dev/null +++ b/dist/nvi/vi/v_xchar.c @@ -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 index 000000000..19d08cb79 --- /dev/null +++ b/dist/nvi/vi/v_yank.c @@ -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 index 000000000..0f9595a9b --- /dev/null +++ b/dist/nvi/vi/v_z.c @@ -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 index 000000000..0277da0a1 --- /dev/null +++ b/dist/nvi/vi/v_zexit.c @@ -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 index 000000000..44e6403f5 --- /dev/null +++ b/dist/nvi/vi/vi.c @@ -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, ¬used, 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 index 000000000..540b0061c --- /dev/null +++ b/dist/nvi/vi/vi.h @@ -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 index 000000000..1b3467b13 --- /dev/null +++ b/dist/nvi/vi/vs_line.c @@ -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 index 000000000..fb83708c1 --- /dev/null +++ b/dist/nvi/vi/vs_msg.c @@ -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, ¬used, &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, ¬used, &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 index 000000000..d052c826e --- /dev/null +++ b/dist/nvi/vi/vs_refresh.c @@ -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, ¬used); + 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 index 000000000..f015cfd7f --- /dev/null +++ b/dist/nvi/vi/vs_relative.c @@ -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 index 000000000..1e21d8217 --- /dev/null +++ b/dist/nvi/vi/vs_smap.c @@ -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 index 000000000..51f16651f --- /dev/null +++ b/dist/nvi/vi/vs_split.c @@ -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); +} diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index a5111e38a..5f3100e23 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -214,9 +214,9 @@ ./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 @@ -230,7 +230,7 @@ ./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 @@ -333,7 +333,7 @@ ./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 @@ -399,6 +399,7 @@ ./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 @@ -504,6 +505,7 @@ ./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 @@ -702,6 +704,9 @@ ./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 @@ -1016,6 +1021,9 @@ ./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 @@ -1172,8 +1180,8 @@ ./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 @@ -1190,7 +1198,7 @@ ./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 @@ -1288,7 +1296,7 @@ ./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 @@ -1346,6 +1354,8 @@ ./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 @@ -1357,7 +1367,7 @@ ./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 @@ -1968,8 +1978,11 @@ ./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 @@ -2029,6 +2042,18 @@ ./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 @@ -2354,6 +2379,9 @@ ./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 @@ -3319,6 +3347,11 @@ ./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 @@ -3545,6 +3578,7 @@ ./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 @@ -3604,7 +3638,7 @@ ./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 diff --git a/etc/mtree/NetBSD.dist.base b/etc/mtree/NetBSD.dist.base index c27b477e7..f251f34ae 100644 --- a/etc/mtree/NetBSD.dist.base +++ b/etc/mtree/NetBSD.dist.base @@ -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 diff --git a/lib/Makefile b/lib/Makefile index d354e13e2..da4349856 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -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") diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index b3bef76cf..0880363d1 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -1,27 +1,134 @@ -## $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 index d3abb2f7b..000000000 --- a/lib/libedit/README +++ /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 index 000000000..e06fcebff --- /dev/null +++ b/lib/libedit/TEST/Makefile @@ -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 index 000000000..78ff518e6 --- /dev/null +++ b/lib/libedit/TEST/rl1.c @@ -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 index 000000000..77f8a5153 --- /dev/null +++ b/lib/libedit/TEST/tc1.c @@ -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 index 000000000..365bd2e66 --- /dev/null +++ b/lib/libedit/TEST/wtc1.c @@ -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 index 000000000..fb75de8f4 --- /dev/null +++ b/lib/libedit/chared.c @@ -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 index 000000000..176475ac8 --- /dev/null +++ b/lib/libedit/chared.h @@ -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 index 000000000..8766aacad --- /dev/null +++ b/lib/libedit/chartype.c @@ -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 index 000000000..b85a57824 --- /dev/null +++ b/lib/libedit/chartype.h @@ -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 index 000000000..1726b0f81 --- /dev/null +++ b/lib/libedit/common.c @@ -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 index cfdff493f..000000000 --- a/lib/libedit/complete.c +++ /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 index 000000000..a42cf02b3 --- /dev/null +++ b/lib/libedit/config.h @@ -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 index 000000000..e869161d7 --- /dev/null +++ b/lib/libedit/editline.3 @@ -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 index feda30b34..000000000 --- a/lib/libedit/editline.c +++ /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) */ - -/* -** 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; - } -} - - -/* -** 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(); -} - - -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 -} - - -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 index b63b69d90..000000000 --- a/lib/libedit/editline.h +++ /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 index 000000000..0c01605b0 --- /dev/null +++ b/lib/libedit/editrc.5 @@ -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 index 000000000..d62790c1f --- /dev/null +++ b/lib/libedit/el.c @@ -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 index 000000000..70c67b8b9 --- /dev/null +++ b/lib/libedit/el.h @@ -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 index 000000000..1b829c2c6 --- /dev/null +++ b/lib/libedit/eln.c @@ -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 index 000000000..ab1e2dfe1 --- /dev/null +++ b/lib/libedit/emacs.c @@ -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 index 000000000..5e98cf564 --- /dev/null +++ b/lib/libedit/filecomplete.c @@ -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 index 000000000..971e6e059 --- /dev/null +++ b/lib/libedit/filecomplete.h @@ -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 index 000000000..77dbaabc4 --- /dev/null +++ b/lib/libedit/hist.c @@ -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 index 000000000..a63be499d --- /dev/null +++ b/lib/libedit/hist.h @@ -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 index 000000000..61f987587 --- /dev/null +++ b/lib/libedit/histedit.h @@ -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 index 000000000..7e8f5209c --- /dev/null +++ b/lib/libedit/history.c @@ -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 index 000000000..1cab508fa --- /dev/null +++ b/lib/libedit/keymacro.c @@ -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 index 000000000..2445de5a5 --- /dev/null +++ b/lib/libedit/keymacro.h @@ -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 index 000000000..588397bc6 --- /dev/null +++ b/lib/libedit/makelist @@ -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 index 000000000..802c37174 --- /dev/null +++ b/lib/libedit/map.c @@ -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 index 000000000..8e0c7e4ea --- /dev/null +++ b/lib/libedit/map.h @@ -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 index 000000000..f1c4391a2 --- /dev/null +++ b/lib/libedit/parse.c @@ -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 index 000000000..ec04051bc --- /dev/null +++ b/lib/libedit/parse.h @@ -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 index 000000000..48b2d27f8 --- /dev/null +++ b/lib/libedit/prompt.c @@ -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 index 000000000..af63b82b6 --- /dev/null +++ b/lib/libedit/prompt.h @@ -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 index 000000000..74796b1db --- /dev/null +++ b/lib/libedit/read.c @@ -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 index 000000000..852606a9c --- /dev/null +++ b/lib/libedit/read.h @@ -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 index 000000000..8d6a1b414 --- /dev/null +++ b/lib/libedit/readline.c @@ -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 index 000000000..3d5111fe3 --- /dev/null +++ b/lib/libedit/readline/Makefile @@ -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 index 000000000..0d1371345 --- /dev/null +++ b/lib/libedit/readline/readline.h @@ -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 index 000000000..3e1176ece --- /dev/null +++ b/lib/libedit/refresh.c @@ -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 index 000000000..f80be4635 --- /dev/null +++ b/lib/libedit/refresh.h @@ -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 index 000000000..762b40604 --- /dev/null +++ b/lib/libedit/search.c @@ -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 index 000000000..d9f27e561 --- /dev/null +++ b/lib/libedit/search.h @@ -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 index 000000000..778486cf3 --- /dev/null +++ b/lib/libedit/shlib_version @@ -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 index 000000000..a5a8a895e --- /dev/null +++ b/lib/libedit/sig.c @@ -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 index 000000000..c957cfdf5 --- /dev/null +++ b/lib/libedit/sig.h @@ -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 index 000000000..690e1354b --- /dev/null +++ b/lib/libedit/sys.h @@ -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 index 0bee530fe..000000000 --- a/lib/libedit/sysunix.c +++ /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 index 000000000..c4a2543e4 --- /dev/null +++ b/lib/libedit/terminal.c @@ -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 index 000000000..c50736305 --- /dev/null +++ b/lib/libedit/terminal.h @@ -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 index 525436c5d..000000000 --- a/lib/libedit/testit.c +++ /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 index 000000000..7fd842d48 --- /dev/null +++ b/lib/libedit/tokenizer.c @@ -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 index 000000000..57c8ee891 --- /dev/null +++ b/lib/libedit/tty.c @@ -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 index 000000000..7bdb0b2bb --- /dev/null +++ b/lib/libedit/tty.h @@ -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 index e387b2da0..000000000 --- a/lib/libedit/unix.h +++ /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 index 000000000..ec9abbd70 --- /dev/null +++ b/lib/libedit/vi.c @@ -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); +} diff --git a/man/man1/Makefile b/man/man1/Makefile index 342b8686f..a194be171 100644 --- a/man/man1/Makefile +++ b/man/man1/Makefile @@ -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 index 7aa317586..000000000 --- a/man/man1/ctags.1 +++ /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 index 504ac9374..000000000 --- a/man/man1/elvis.1 +++ /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 index b541c2ed1..000000000 --- a/man/man1/elvrec.1 +++ /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 index 3c731faf5..000000000 --- a/man/man1/fmt.1 +++ /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 index e7d2e178f..000000000 --- a/man/man1/ref.1 +++ /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 diff --git a/man/man1x/Makefile b/man/man1x/Makefile index a70b7a434..d251e1905 100644 --- a/man/man1x/Makefile +++ b/man/man1x/Makefile @@ -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 index 27146927f..000000000 --- a/man/man1x/elvis.1x +++ /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. diff --git a/man/man8/Makefile b/man/man8/Makefile index ac6cc6cf2..e07795717 100644 --- a/man/man8/Makefile +++ b/man/man8/Makefile @@ -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 index 4b1f92206..000000000 --- a/man/man8/elvprsv.8 +++ /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 diff --git a/releasetools/nbsd_ports b/releasetools/nbsd_ports index cb1a410cd..efec301e3 100644 --- a/releasetools/nbsd_ports +++ b/releasetools/nbsd_ports @@ -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 @@ -114,6 +116,7 @@ 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 @@ -130,6 +133,7 @@ 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 diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 53984bb4c..b2b9d85d6 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -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 index 000000000..9d32b2249 --- /dev/null +++ b/usr.bin/ctags/C.c @@ -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 index 000000000..5bc61f974 --- /dev/null +++ b/usr.bin/ctags/Makefile @@ -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 index 000000000..649ba63b6 --- /dev/null +++ b/usr.bin/ctags/ctags.1 @@ -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 index 000000000..5054b1b3a --- /dev/null +++ b/usr.bin/ctags/ctags.c @@ -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 index 000000000..6aa2aa1ba --- /dev/null +++ b/usr.bin/ctags/ctags.h @@ -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 index 000000000..2a9cefdb9 --- /dev/null +++ b/usr.bin/ctags/fortran.c @@ -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 index 000000000..d143c6c50 --- /dev/null +++ b/usr.bin/ctags/lisp.c @@ -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 index 000000000..86fcd3a28 --- /dev/null +++ b/usr.bin/ctags/print.c @@ -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 index 000000000..658a073bf --- /dev/null +++ b/usr.bin/ctags/test/ctags.test @@ -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 index 000000000..93f4a413d --- /dev/null +++ b/usr.bin/ctags/tree.c @@ -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 index 000000000..d17fa99d7 --- /dev/null +++ b/usr.bin/ctags/yacc.c @@ -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 index 000000000..f9540332c --- /dev/null +++ b/usr.bin/nvi/Makefile @@ -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 index 000000000..317363178 --- /dev/null +++ b/usr.bin/nvi/Makefile.inc @@ -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 index 000000000..5b0eb5fd0 --- /dev/null +++ b/usr.bin/nvi/build/Makefile @@ -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 index 000000000..4300f830d --- /dev/null +++ b/usr.bin/nvi/build/config.h @@ -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 index 000000000..6dd0bf14e --- /dev/null +++ b/usr.bin/nvi/build/pathnames.h @@ -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 index 000000000..b7cf93a43 --- /dev/null +++ b/usr.bin/nvi/build/port.h @@ -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 index 000000000..6a3cbecb7 --- /dev/null +++ b/usr.bin/nvi/catalog/Makefile @@ -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 index 000000000..13e122d4c --- /dev/null +++ b/usr.bin/nvi/docs/Makefile @@ -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 index 000000000..0cf5b9a52 --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/Makefile @@ -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 index 000000000..f17888e9b --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/edit/Makefile @@ -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 index 000000000..613d5b4d8 --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/edit/edit.vindex @@ -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 index 000000000..8501b857f --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/exref/Makefile @@ -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 index 000000000..5b1628ccd --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/vi.ref/Makefile @@ -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 index 000000000..4bea0846e --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/vi.ref/ex.cmd.roff @@ -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 index 000000000..8453b1de8 --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/vi.ref/merge.awk @@ -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 index 000000000..e37343c97 --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/vi.ref/set.opt.roff @@ -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 index 000000000..d515f971b --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/vi.ref/vi.cmd.roff @@ -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 index 000000000..22471209c --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/vi.ref/vi.ref @@ -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 index 000000000..ded95e5f7 --- /dev/null +++ b/usr.bin/nvi/docs/USD.doc/vitut/Makefile @@ -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 index 000000000..144295a31 --- /dev/null +++ b/usr.bin/nvi/docs/ev @@ -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 index 000000000..7391a1ccf --- /dev/null +++ b/usr.bin/nvi/docs/help @@ -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 index 000000000..007c8db4f --- /dev/null +++ b/usr.bin/nvi/docs/info/Makefile @@ -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 index 000000000..dbad6c8ba --- /dev/null +++ b/usr.bin/nvi/docs/internals/autowrite @@ -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 index 000000000..8b1db3276 --- /dev/null +++ b/usr.bin/nvi/docs/internals/context @@ -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 index 000000000..a1122343c --- /dev/null +++ b/usr.bin/nvi/docs/internals/gdb.script @@ -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 index 000000000..9a7506ee2 --- /dev/null +++ b/usr.bin/nvi/docs/internals/input @@ -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 index 000000000..c64b76774 --- /dev/null +++ b/usr.bin/nvi/docs/internals/openmode @@ -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 index 000000000..a5fb8926a --- /dev/null +++ b/usr.bin/nvi/docs/internals/quoting @@ -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 index 000000000..a25c780c8 --- /dev/null +++ b/usr.bin/nvi/docs/internals/structures @@ -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 index 000000000..bdc8b5f2d --- /dev/null +++ b/usr.bin/nvi/recover/Makefile @@ -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 index 000000000..bd1c9850e --- /dev/null +++ b/usr.bin/nvi/recover/virecover @@ -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 index 000000000..dafc3d11b --- /dev/null +++ b/usr.bin/nvi/recover/virecover.8 @@ -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 .