|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char *sccsid = "@(#)ex_addr.c 7.5 (Berkeley) 7/22/88"; ! 9: #endif not lint ! 10: ! 11: #include "ex.h" ! 12: #include "ex_re.h" ! 13: ! 14: /* ! 15: * Routines for address parsing and assignment and checking of address bounds ! 16: * in command mode. The routine address is called from ex_cmds.c ! 17: * to parse each component of a command (terminated by , ; or the beginning ! 18: * of the command itself. It is also called by the scanning routine ! 19: * in ex_voperate.c from within open/visual. ! 20: * ! 21: * Other routines here manipulate the externals addr1 and addr2. ! 22: * These are the first and last lines for the current command. ! 23: * ! 24: * The variable bigmove remembers whether a non-local glitch of . was ! 25: * involved in an address expression, so we can set the previous context ! 26: * mark '' when such a motion occurs. ! 27: */ ! 28: ! 29: static bool bigmove; ! 30: ! 31: /* ! 32: * Set up addr1 and addr2 for commands whose default address is dot. ! 33: */ ! 34: setdot() ! 35: { ! 36: ! 37: setdot1(); ! 38: if (bigmove) ! 39: markDOT(); ! 40: } ! 41: ! 42: /* ! 43: * Call setdot1 to set up default addresses without ever ! 44: * setting the previous context mark. ! 45: */ ! 46: setdot1() ! 47: { ! 48: ! 49: if (addr2 == 0) ! 50: addr1 = addr2 = dot; ! 51: if (addr1 > addr2) { ! 52: notempty(); ! 53: error("Addr1 > addr2|First address exceeds second"); ! 54: } ! 55: } ! 56: ! 57: /* ! 58: * Ex allows you to say ! 59: * delete 5 ! 60: * to delete 5 lines, etc. ! 61: * Such nonsense is implemented by setcount. ! 62: */ ! 63: setcount() ! 64: { ! 65: register int cnt; ! 66: ! 67: pastwh(); ! 68: if (!isdigit(peekchar())) { ! 69: setdot(); ! 70: return; ! 71: } ! 72: addr1 = addr2; ! 73: setdot(); ! 74: cnt = getnum(); ! 75: if (cnt <= 0) ! 76: error("Bad count|Nonzero count required"); ! 77: addr2 += cnt - 1; ! 78: if (addr2 > dol) ! 79: addr2 = dol; ! 80: nonzero(); ! 81: } ! 82: ! 83: /* ! 84: * Parse a number out of the command input stream. ! 85: */ ! 86: getnum() ! 87: { ! 88: register int cnt; ! 89: ! 90: for (cnt = 0; isdigit(peekcd());) ! 91: cnt = cnt * 10 + ex_getchar() - '0'; ! 92: return (cnt); ! 93: } ! 94: ! 95: /* ! 96: * Set the default addresses for commands which use the whole ! 97: * buffer as default, notably write. ! 98: */ ! 99: setall() ! 100: { ! 101: ! 102: if (addr2 == 0) { ! 103: addr1 = one; ! 104: addr2 = dol; ! 105: if (dol == zero) { ! 106: dot = zero; ! 107: return; ! 108: } ! 109: } ! 110: /* ! 111: * Don't want to set previous context mark so use setdot1(). ! 112: */ ! 113: setdot1(); ! 114: } ! 115: ! 116: /* ! 117: * No address allowed on, e.g. the file command. ! 118: */ ! 119: setnoaddr() ! 120: { ! 121: ! 122: if (addr2 != 0) ! 123: error("No address allowed@on this command"); ! 124: } ! 125: ! 126: /* ! 127: * Parse an address. ! 128: * Just about any sequence of address characters is legal. ! 129: * ! 130: * If you are tricky you can use this routine and the = command ! 131: * to do simple addition and subtraction of cardinals less ! 132: * than the number of lines in the file. ! 133: */ ! 134: line * ! 135: address(inputline) ! 136: char *inputline; ! 137: { ! 138: register line *addr; ! 139: register int offset, c; ! 140: short lastsign; ! 141: ! 142: bigmove = 0; ! 143: lastsign = 0; ! 144: offset = 0; ! 145: addr = 0; ! 146: for (;;) { ! 147: if (isdigit(peekcd())) { ! 148: if (addr == 0) { ! 149: addr = zero; ! 150: bigmove = 1; ! 151: } ! 152: loc1 = 0; ! 153: addr += offset; ! 154: offset = getnum(); ! 155: if (lastsign >= 0) ! 156: addr += offset; ! 157: else ! 158: addr -= offset; ! 159: lastsign = 0; ! 160: offset = 0; ! 161: } ! 162: switch (c = getcd()) { ! 163: ! 164: case '?': ! 165: case '/': ! 166: case '$': ! 167: case '\'': ! 168: case '\\': ! 169: bigmove++; ! 170: case '.': ! 171: if (addr || offset) ! 172: error("Badly formed address"); ! 173: } ! 174: offset += lastsign; ! 175: lastsign = 0; ! 176: switch (c) { ! 177: ! 178: case ' ': ! 179: case '\t': ! 180: continue; ! 181: ! 182: case '+': ! 183: lastsign = 1; ! 184: if (addr == 0) ! 185: addr = dot; ! 186: continue; ! 187: ! 188: case '^': ! 189: case '-': ! 190: lastsign = -1; ! 191: if (addr == 0) ! 192: addr = dot; ! 193: continue; ! 194: ! 195: case '\\': ! 196: case '?': ! 197: case '/': ! 198: c = compile(c, 1); ! 199: notempty(); ! 200: savere(scanre); ! 201: addr = dot; ! 202: if (inputline && execute(0, dot)) { ! 203: if (c == '/') { ! 204: while (loc1 <= inputline) { ! 205: if (loc1 == loc2) ! 206: loc2++; ! 207: if (!execute(1)) ! 208: goto nope; ! 209: } ! 210: break; ! 211: } else if (loc1 < inputline) { ! 212: char *last; ! 213: doques: ! 214: ! 215: do { ! 216: last = loc1; ! 217: if (loc1 == loc2) ! 218: loc2++; ! 219: if (!execute(1)) ! 220: break; ! 221: } while (loc1 < inputline); ! 222: loc1 = last; ! 223: break; ! 224: } ! 225: } ! 226: nope: ! 227: for (;;) { ! 228: if (c == '/') { ! 229: addr++; ! 230: if (addr > dol) { ! 231: if (value(WRAPSCAN) == 0) ! 232: error("No match to BOTTOM|Address search hit BOTTOM without matching pattern"); ! 233: addr = zero; ! 234: } ! 235: } else { ! 236: addr--; ! 237: if (addr < zero) { ! 238: if (value(WRAPSCAN) == 0) ! 239: error("No match to TOP|Address search hit TOP without matching pattern"); ! 240: addr = dol; ! 241: } ! 242: } ! 243: if (execute(0, addr)) { ! 244: if (inputline && c == '?') { ! 245: inputline = &linebuf[LBSIZE]; ! 246: goto doques; ! 247: } ! 248: break; ! 249: } ! 250: if (addr == dot) ! 251: error("Fail|Pattern not found"); ! 252: } ! 253: continue; ! 254: ! 255: case '$': ! 256: addr = dol; ! 257: continue; ! 258: ! 259: case '.': ! 260: addr = dot; ! 261: continue; ! 262: ! 263: case '\'': ! 264: c = markreg(ex_getchar()); ! 265: if (c == 0) ! 266: error("Marks are ' and a-z"); ! 267: addr = getmark(c); ! 268: if (addr == 0) ! 269: error("Undefined mark@referenced"); ! 270: break; ! 271: ! 272: default: ! 273: ungetchar(c); ! 274: if (offset) { ! 275: if (addr == 0) ! 276: addr = dot; ! 277: addr += offset; ! 278: loc1 = 0; ! 279: } ! 280: if (addr == 0) { ! 281: bigmove = 0; ! 282: return (0); ! 283: } ! 284: if (addr != zero) ! 285: notempty(); ! 286: addr += lastsign; ! 287: if (addr < zero) ! 288: error("Negative address@- first buffer line is 1"); ! 289: if (addr > dol) ! 290: error("Not that many lines@in buffer"); ! 291: return (addr); ! 292: } ! 293: } ! 294: } ! 295: ! 296: /* ! 297: * Abbreviations to make code smaller ! 298: * Left over from squashing ex version 1.1 into ! 299: * 11/34's and 11/40's. ! 300: */ ! 301: setCNL() ! 302: { ! 303: ! 304: setcount(); ! 305: newline(); ! 306: } ! 307: ! 308: setNAEOL() ! 309: { ! 310: ! 311: setnoaddr(); ! 312: eol(); ! 313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.