diff options
Diffstat (limited to 'ex_addr.c')
-rw-r--r-- | ex_addr.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/ex_addr.c b/ex_addr.c new file mode 100644 index 0000000..ffd8db8 --- /dev/null +++ b/ex_addr.c @@ -0,0 +1,406 @@ +/* + * This code contains changes by + * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved. + * + * Conditions 1, 2, and 4 and the no-warranty notice below apply + * to these changes. + * + * + * 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. 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(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * Redistributions of source code and documentation must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. + * 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. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of + * other contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, 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 CALDERA INTERNATIONAL, INC. 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 lint +#ifdef DOSCCS +static char sccsid[] = "@(#)ex_addr.c 1.10 (gritter) 2/17/05"; +#endif +#endif /* not lint */ + +/* from ex_addr.c 7.3 (Berkeley) 6/7/85 */ + +#include "ex.h" +#include "ex_re.h" + +/* + * Routines for address parsing and assignment and checking of address bounds + * in command mode. The routine address is called from ex_cmds.c + * to parse each component of a command (terminated by , ; or the beginning + * of the command itself. It is also called by the scanning routine + * in ex_voperate.c from within open/visual. + * + * Other routines here manipulate the externals addr1 and addr2. + * These are the first and last lines for the current command. + * + * The variable bigmove remembers whether a non-local glitch of . was + * involved in an address expression, so we can set the previous context + * mark '' when such a motion occurs. + */ + +static bool bigmove; + +/* + * Set up addr1 and addr2 for commands whose default address is dot. + */ +void +setdot(void) +{ + + setdot1(); + if (bigmove) + markDOT(); +} + +/* + * Call setdot1 to set up default addresses without ever + * setting the previous context mark. + */ +void +setdot1(void) +{ + + if (addr2 == 0) + addr1 = addr2 = dot; + if (addr1 > addr2) { + notempty(); + failed = 1; + error(catgets(catd, 1, 6, + "Addr1 > addr2|First address exceeds second")); + } +} + +/* + * Ex allows you to say + * delete 5 + * to delete 5 lines, etc. + * Such nonsense is implemented by setcount. + */ +void +setcount(void) +{ + register int cnt; + + pastwh(); + if (!isdigit(peekchar())) { + setdot(); + return; + } + addr1 = addr2; + setdot(); + cnt = getnum(); + if (cnt <= 0) + error(catgets(catd, 1, 7, "Bad count|Nonzero count required")); + addr2 += cnt - 1; + if (addr2 > dol) + addr2 = dol; + nonzero(); +} + +/* + * Parse a number out of the command input stream. + */ +int +getnum(void) +{ + register int cnt; + + for (cnt = 0; isdigit(peekcd());) + cnt = cnt * 10 + getchar() - '0'; + return (cnt); +} + +/* + * Set the default addresses for commands which use the whole + * buffer as default, notably write. + */ +void +setall(void) +{ + + if (addr2 == 0) { + addr1 = one; + addr2 = dol; + if (dol == zero) { + dot = zero; + return; + } + } + /* + * Don't want to set previous context mark so use setdot1(). + */ + setdot1(); +} + +/* + * No address allowed on, e.g. the file command. + */ +void +setnoaddr(void) +{ + + if (addr2 != 0) { + failed = 1; + error(catgets(catd, 1, 8, + "No address allowed@on this command")); + } +} + +/* + * Parse an address. + * Just about any sequence of address characters is legal. + * + * If you are tricky you can use this routine and the = command + * to do simple addition and subtraction of cardinals less + * than the number of lines in the file. + */ +line * +address(char *in_line) +{ + register line *addr; + register int offset, c; + short lastsign; + + bigmove = 0; + lastsign = 0; + offset = 0; + addr = 0; + for (;;) { + if (isdigit(peekcd())) { + if (addr == 0) { + addr = zero; + bigmove = 1; + } + loc1 = 0; + addr += offset; + offset = getnum(); + if (lastsign >= 0) + addr += offset; + else + addr -= offset; + lastsign = 0; + offset = 0; + } + switch (c = getcd()) { + + case '?': + case '/': + case '$': + case '\'': + case '\\': + bigmove++; + case '.': + if (addr || offset) + error(catgets(catd, 1, 9, + "Badly formed address")); + } + offset += lastsign; + lastsign = 0; + switch (c) { + + case ' ': + case '\t': + continue; + + case '+': + lastsign = 1; + if (addr == 0) + addr = dot; + continue; + + case '^': + case '-': + lastsign = -1; + if (addr == 0) + addr = dot; + continue; + + case '\\': + case '?': + case '/': + c = compile(c, 1); + notempty(); + savere(&scanre); + addr = dot; + if (in_line && execute(0, dot)) { + if (c == '/') { + while (loc1 <= in_line) { + if (loc1 == loc2) + loc2++; + if (!execute(1, NULL)) + goto nope; + } + break; + } else if (loc1 < in_line) { + char *last; +doques: + + do { + last = loc1; + if (loc1 == loc2) + loc2++; + if (!execute(1, NULL)) + break; + } while (loc1 < in_line); + loc1 = last; + break; + } + } +nope: + for (;;) { + if (c == '/') { + addr++; + if (addr > dol) { + if (value(WRAPSCAN) == 0) +error(catgets(catd, 1, 10, "No match to BOTTOM|Address search hit BOTTOM without matching pattern")); + addr = zero; + } + } else { + addr--; + if (addr < zero) { + if (value(WRAPSCAN) == 0) +error(catgets(catd, 1, 11, "No match to TOP|Address search hit TOP without matching pattern")); + addr = dol; + } + } + if (execute(0, addr)) { + if (in_line && c == '?') { + in_line = &linebuf[LBSIZE]; + goto doques; + } + break; + } + if (addr == dot) + error(catgets(catd, 1, 12, + "Fail|Pattern not found")); + } + continue; + + case '$': + addr = dol; + continue; + + case '.': + addr = dot; + continue; + + case '\'': + c = markreg(getchar()); + if (c == 0) + error(catgets(catd, 1, 13, + "Marks are ' and a-z")); + addr = getmark(c); + if (addr == 0) + error(catgets(catd, 1, 14, + "Undefined mark@referenced")); + break; + + default: + ungetchar(c); + if (offset) { + if (addr == 0) + addr = dot; + addr += offset; + loc1 = 0; + } + if (addr == 0) { + bigmove = 0; + return (0); + } + if (addr != zero) + notempty(); + addr += lastsign; + if (addr < zero) { + failed = 1; + error(catgets(catd, 1, 15, + "Negative address@- first buffer line is 1")); + } + if (addr > dol) { + failed = 1; + error(catgets(catd, 1, 16, + "Not that many lines@in buffer")); + } + return (addr); + } + } +} + +/* + * Abbreviations to make code smaller + * Left over from squashing ex version 1.1 into + * 11/34's and 11/40's. + */ +void +setCNL(void) +{ + + setcount(); + newline(); +} + +void +setNAEOL(void) +{ + + setnoaddr(); + eol(); +} |