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